#ifndef _FOR_MAT_H
#define _FOR_MAT_H
#include "util.hpp"
#include "level.hpp"
#include "message.hpp"
#include <vector>
#include<iostream>
#include<sstream>
namespace tqblog
{
    class FormatItem
    {
    public:
        using ptr = std::shared_ptr<FormatItem>;
        virtual void format(std::ostream &out, LogMsg &msg) {}
    };
    class TimeFormatItem : public FormatItem
    {
    public:
        TimeFormatItem(const std::string &format = "%H:%M:%S") : format_(format) {}
        virtual void format(std::ostream &out, LogMsg &msg)
        {
            struct tm lt;
            time_t timep = tqblog::util::Date::now();
            localtime_r(&timep, &lt);
            char arr[128] = {0};
            strftime(arr, 127, format_.c_str(), &lt);
            out << arr;
        }
        const std::string format_;
    };
    class LevelFormatItem : public FormatItem
    {
    public:
        virtual void format(std::ostream &out, LogMsg &msg)
        {
            out << LogLevel::toString(msg._level);
        }
    };
    class LineFormatItem : public FormatItem
    {
    public:
        virtual void format(std::ostream &out, LogMsg &msg)
        {
            out << msg._line;
        }
    };
    class IdFormatItem : public FormatItem
    {
    public:
        virtual void format(std::ostream &out, LogMsg &msg)
        {
            out << msg._tid;
        }
    };
    class LoggerFormatItem : public FormatItem
    {
    public:
        virtual void format(std::ostream &out, LogMsg &msg)
        {
            out << msg._logger;
        }
    };
    class FileFormatItem : public FormatItem
    {
    public:
        virtual void format(std::ostream &out, LogMsg &msg)
        {
            out << msg._file;
        }
    };
    class PayloadFormatItem : public FormatItem
    {
    public:
        virtual void format(std::ostream &out, LogMsg &msg)
        {
            out << msg._payload;
        }
    };
    class NewlineFormatItem : public FormatItem
    {
    public:
        virtual void format(std::ostream &out, LogMsg &msg)
        {
            out << "\n";
        }
    };
      class TabFormatItem : public FormatItem
    {
    public:
        virtual void format(std::ostream &out, LogMsg &msg)
        {
            out << "\t";
        }
    };
     class otherFormatItem : public FormatItem
    {
    public:
         otherFormatItem(const std::string &ss):ss_(ss){}
    private:
        virtual void format(std::ostream &out, LogMsg &msg)
        {
            out<<ss_;
        }
        const std::string ss_;
    };
    class Formatter
    {
    public:
        Formatter(std::string pattern="[%d{%Y:%m:%d:%H:%M:%S}][%p]%T%m%n"):pattern_(pattern){}
        std::string format(LogMsg &msg)
        {
            std::stringstream ss;
            for(auto it:items_){
                it->format(ss,msg);
            }
            
            return ss.str();
        }
        std::ostream& format(std::ostream &os, LogMsg &msg)
        {
            for(auto it:items_){
                it->format(os,msg);
            }
            return os;
        }
        FormatItem::ptr createItem(const std::string& key, const std::string& value)
        {
            if (key=="f")return FormatItem::ptr(new FileFormatItem);
            if (key=="p")return FormatItem::ptr(new LevelFormatItem);
            if (key=="m")return FormatItem::ptr(new PayloadFormatItem);
            if (key=="c")return FormatItem::ptr(new LoggerFormatItem);
            if (key=="t")return FormatItem::ptr(new TabFormatItem);
            if (key=="l")return FormatItem::ptr(new LineFormatItem);
            if (key=="n")return FormatItem::ptr(new NewlineFormatItem);
            if (key=="T")return FormatItem::ptr(new TabFormatItem);
            if (key=="d")return FormatItem::ptr(new TimeFormatItem(value));
            return FormatItem::ptr(new otherFormatItem(value));
        }
        bool parsepattern()
        {
            int pos = 0;
            std::string key = "";
            std::string value = "";
            std::vector<std::pair<std::string, std::string>> format_order;
            while (pos < pattern_.size())
            {
                if (pattern_[pos] != '%')
                { // 普通字符串
                    value += pattern_[pos++];
                    format_order.push_back(make_pair(key, value));
                    key.erase();
                    value.erase();
                }
                else if (pattern_[pos] == '%'&&pattern_[pos+1] != '%')
                {
                    key = pattern_[++pos];
                    pos++;
                    if (pattern_[pos] == '{')
                    {
                        pos++;
                        while (pos < pattern_.size() && pattern_[pos] != '}')
                        {
                            value += pattern_[pos++];
                        }
                        if (pattern_[pos] != '}')
                        {
                            std::cout << "格式错误缺少'}'" << std::endl;
                            return false;
                        }
                        else
                        {
                            pos++;
                        }
                        
                    }
                    format_order.push_back(make_pair(key, value));
                    key.erase();
                    value.erase();
                }
                else{
                    value+='%';
                    format_order.push_back(make_pair(key, value));
                    key.erase();
                    value.erase();
                    pos+=2;
                }
            }
            for(auto it:format_order){
                items_.push_back(createItem(it.first,it.second));
            }
        }

    private:
        std::string pattern_;
        std::vector<FormatItem::ptr> items_;
    };
}

#endif